#include "glutils.hpp"

#define _USE_MATH_DEFINES

#include <math.h>
#include <cstring>
#include <cstdlib>
#include <iostream>

static SDL_Surface *flipSurface(SDL_Surface * surface);

GLuint GLUtils::loadTexture(const char * filename)
{
    SDL_Surface *picture_surface = NULL;
    SDL_Surface *gl_surface = NULL;
    SDL_Surface *gl_fliped_surface = NULL;
    Uint32	rmask,gmask,bmask,amask;
    GLuint	glID;

    picture_surface = IMG_Load(filename);
    if (picture_surface == NULL)
        return (0);
    if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
      {
	rmask = 0xff000000;
	gmask = 0x00ff0000;
	bmask = 0x0000ff00;
	amask = 0x000000ff;
      }
    else
      {
	rmask = 0x000000ff;
	gmask = 0x0000ff00;
	bmask = 0x00ff0000;
	amask = 0xff000000;
      }
    SDL_PixelFormat format = *(picture_surface->format);
    format.BitsPerPixel = 32;
    format.BytesPerPixel = 4;
    format.Rmask = rmask;
    format.Gmask = gmask;
    format.Bmask = bmask;
    format.Amask = amask;
    gl_surface = SDL_ConvertSurface(picture_surface,&format,SDL_SWSURFACE);
    gl_fliped_surface = flipSurface(gl_surface);
    glGenTextures(1, &glID);
    glBindTexture(GL_TEXTURE_2D, glID);
    gluBuild2DMipmaps(GL_TEXTURE_2D, 4, gl_fliped_surface->w,
                      gl_fliped_surface->h, GL_RGBA,GL_UNSIGNED_BYTE,
		      gl_fliped_surface->pixels);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    SDL_FreeSurface(gl_fliped_surface);
    SDL_FreeSurface(gl_surface);
    SDL_FreeSurface(picture_surface);
    return (glID);
}

void	GLUtils::writeTextGL(const std::string& texte, TTF_Font* police, SDL_Color& c, int x, int y)
{
  SDL_Rect	pos;
  SDL_Surface	*str = NULL;
  GLuint	texture = 0;
  int		width, height;
  float		ratio_width, ratio_height;

  if (!(str = TTF_RenderText_Blended(police, texte.c_str(), c)))
    return ;
  pos.x = x;
  pos.y = y;
  glGenTextures(1, &texture);
  glBindTexture(GL_TEXTURE_2D, texture);
  width = (int)(pow(2, ceil(log((float)str->w) / log(2.0))) + 0.5);
  height = (int)(pow(2, ceil(log((float)str->h) / log(2.0))) + 0.5);
  ratio_width = (float)str->w / (float)width;
  ratio_height = (float)str->h / (float)height;
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, str->w, str->h, GL_RGBA, GL_UNSIGNED_BYTE, str->pixels);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glBegin(GL_QUADS);
    glTexCoord2f(0, 0);				glVertex2d(pos.x, pos.y);
    glTexCoord2f(ratio_width, 0);		glVertex2d(pos.x + str->w, pos.y);
    glTexCoord2f(ratio_width, ratio_height);	glVertex2d(pos.x + str->w, pos.y + str->h);
    glTexCoord2f(0, ratio_height);		glVertex2d(pos.x, pos.y+ str->h);
  glEnd();
  glDeleteTextures(1, &texture);
  SDL_FreeSurface(str);
}

static SDL_Surface *flipSurface(SDL_Surface * surface)
{
    int current_line,pitch;
    SDL_Surface * fliped_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
                                   surface->w, surface->h,
                                   surface->format->BitsPerPixel,
                                   surface->format->Rmask,
                                   surface->format->Gmask,
                                   surface->format->Bmask,
                                   surface->format->Amask);

    SDL_LockSurface(surface);
    SDL_LockSurface(fliped_surface);
    pitch = surface->pitch;
    for (current_line = 0; current_line < surface->h; current_line ++)
      {
	memcpy(&((unsigned char* )fliped_surface->pixels)[current_line*pitch],
               &((unsigned char* )surface->pixels)[(surface->h - 1  -
                                                    current_line)*pitch],
               pitch);
      }
    SDL_UnlockSurface(fliped_surface);
    SDL_UnlockSurface(surface);
    return fliped_surface;
}
